﻿using ICSharpCode.SharpZipLib.Zip;
using OA.Models.ViewModels;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Mvc;

namespace OA.Controllers
{
    /// <summary>
    ///  网盘
    /// </summary>
    public class CloudStorageController : BaseController
    {
        public ActionResult Index()
        {
            return View();
        }

        /// <summary>
        ///  获取面包屑路径
        /// </summary>
        /// <param name="fileId">当前文件夹Id</param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ReadCrumbs(int? fileId)
        {
            var _entity = Context.Files.Find(fileId);
            var _list = new List<CrumbsViewModel>();

            while (_entity != null)
            {
                _list.Add(new CrumbsViewModel()
                {
                    Title = _entity.Name,
                    Href = _entity.Id.ToString()
                });

                _entity = _entity.Parent;
            }

            return Json(_list);
        }
        /// <summary>
        ///  获取文件集
        /// </summary>
        /// <param name="fileId">当前文件夹Id</param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Read(int? fileId)
        {
            var dbset = Context.Files;
            var query = fileId.HasValue ?
                            dbset.Where(d => d.ParentId.Value == fileId.Value) :
                            dbset.Where(d => !d.ParentId.HasValue);

            //var result = query
            //    .OrderByDescending(d => d.IsFolder)
            //    .Select(s => new
            //    {
            //        s.Id,
            //        s.Name,
            //        s.Icon,
            //        s.IsFolder,
            //        s.AbbreviationName
            //    })
            //    .ToList();

            return Json(query);
        }
        /// <summary>
        ///  新建 & 更新文件夹或文件视图
        /// </summary>
        /// <param name="fileId">文件或文件夹Id</param>
        /// <param name="currentId">当前目录Id</param>
        /// <returns></returns>
        public ActionResult Update(int fileId, int currentId)
        {
            var file = Context.Files.Create();

            if (fileId == 0)
            {
                file.IsFolder = true;
                if (currentId != 0)
                {
                    file.ParentId = currentId;
                }
                else
                {
                    file.ParentId = null;
                }
            }
            else
            {
                file = Context.Files.Find(fileId);
            }

            return PartialView(file);
        }
        /// <summary>
        ///  新建 & 更新文件夹或文件
        ///  只有文件夹可以新建
        ///  文件夹和文件都可以更新(重命名)
        ///  相同文件目录下不得有相同的文件名(文件夹名)
        /// </summary>
        /// <param name="file">文件实体</param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Update(Models.File file) 
        {
            var _entity = Context.Files.Find(file.Id);

            if (string.IsNullOrWhiteSpace(file.Name))
            {
                return Json(Failed("文件名不能为空或空格!"));
            }

            if (Context.Files.Any(d => d.ParentId == file.ParentId && d.Name.Equals(file.Name)))
            {
                return Json(Failed("该文件目录下已经有此文件名!"));
            }

            if (file.IsFolder)
            {
                if (_entity == null)
                {
                    _entity = new Models.File()
                    {
                        Name = file.Name,
                        IsFolder = file.IsFolder,
                        ParentId = file.ParentId,
                        CreatDate = DateTime.Now,
                        Creator = HttpContext.User.Identity.Name,
                    };

                    Context.Files.Add(_entity);
                }
                else
                {
                    _entity.Name = file.Name;
                }
            }
            else
            {
                if (_entity == null)
                {
                    _entity = new Models.File()
                    {
                        Name = file.Name,
                        IsFolder = file.IsFolder,
                        ParentId = file.ParentId,
                        Extension = file.Extension,
                        Path = file.Path,
                        CreatDate = DateTime.Now,
                        Creator = (HttpContext.User as CurrentUserCookie).CurrentUser.Name,
                    };

                    Context.Files.Add(_entity);
                }
                else
                {
                    _entity.Name = file.Name;
                }
            }

            try
            {
                Context.SaveChanges();
                return Json(Success("新建成功!", _entity));
            }
            catch (Exception ex)
            {
                return Json(Failed("操作失败:" + ex.Message));
            }
        }
        /// <summary>
        ///  删除文件集
        ///  不允许删除有子文件目录的文件夹
        ///  如果删除多个文件文件过程中碰到不符合删除规则的文件
        ///  则不执行删除动作
        /// </summary>
        /// <param name="FileId">文件Id数组</param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Delete(int[] FileId) 
        {
            var files = new List<Models.File>();

            foreach (var id in FileId)
            {
                var _entity = Context.Files.Find(id);
                if (_entity == null)
                {
                    return Json(Failed("文件不存在!"));
                }
                if (_entity.IsFolder)
                {
                    if (_entity.Children != null && _entity.Children.Count > 0)
                    {
                        return Json(Failed("文件夹" + _entity.Name + "下还有子文件目录存在, 请删除子文件后再试!"));
                    }
                }
                files.Add(_entity);
            }

            try
            {
                Context.Files.RemoveRange(files);
                Context.SaveChanges();
                return Json(Success("删除" + files.Count + "个文件成功!"));
            }
            catch (Exception ex)
            {
                return Json(Failed("删除失败:" + ex.Message));
            }
        }
        /// <summary>
        ///  文件移动
        /// </summary>
        /// <param name="FileId"></param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Move(int FileId) 
        {
            return PartialView();
        }
        /// <summary>
        ///  文件预览
        /// </summary>
        /// <param name="FileId"></param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Preview(int FileId) 
        {
            return PartialView();
        }
        /// <summary>
        ///  文件下载准备
        /// </summary>
        /// <param name="FileId">文件Id集合</param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
        public ActionResult PrepareDownload(int[] FileId)
        {
            var files = new List<Models.File>();
            var _path = "";

            if (FileId != null)
            {
                foreach (var id in FileId)
                {
                    var _entity = Context.Files.Find(id);
                    if (_entity == null)
                    {
                        return Json(Failed("文件不存在!"));
                    }
                    if (_entity.IsFolder)
                    {
                        return Json(Failed("暂不支持文件夹下载!"));
                    }
                    files.Add(_entity);
                }

                if (files.Count == 1)
                {
                    _path = files[0].Path;
                }
                else if (files.Count > 1)
                {
                    // 压缩文件以父文件夹命名
                    var _zipName = (files[0].Parent == null ? Guid.NewGuid().ToString() : files[0].Parent.Name) + ".zip";
                    // 相对路径
                    _path = @"\Files\Zips\" + _zipName;
                    // 绝对路径
                    var _ph = Server.MapPath(@"\Files\Zips\" + _zipName);
                    // 创建zip文件路径
                    if (!Directory.Exists(Server.MapPath(@"\Files\Zips\")))
                    {
                        Directory.CreateDirectory(Server.MapPath(@"\Files\Zips\"));
                    }
                    ZipOutputStream zipOutputStream = new ZipOutputStream(System.IO.File.Create(_ph));

                    foreach (var f in files)
                    {
                        try
                        {
                            var _fpath = AppDomain.CurrentDomain.BaseDirectory + f.Path;
                            FileStream fs = System.IO.File.OpenRead(_fpath);
                            byte[] buffer = new byte[fs.Length];
                            fs.Read(buffer, 0, buffer.Length);

                            ZipEntry entry = new ZipEntry(f.Name);
                            entry.DateTime = DateTime.Now;
                            zipOutputStream.PutNextEntry(entry);
                            zipOutputStream.Write(buffer, 0, buffer.Length);
                            fs.Close();
                            fs.Dispose();
                        }
                        catch(Exception ex)
                        {

                        }
                    }

                    zipOutputStream.Finish();
                    zipOutputStream.Close();
                }
                else
                {
                    return Json(Failed("批量下载失败!"), JsonRequestBehavior.AllowGet);
                }

                return Json(Success("准备下载...", _path), JsonRequestBehavior.AllowGet);
            }

            return Json(Failed("参数错误!"), JsonRequestBehavior.AllowGet);
        }
        /// <summary>
        ///  文件下载
        /// </summary>
        /// <param name="path">文件相对地址</param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Download(string path)
        {
            var _path = Server.MapPath(path);

            if (System.IO.File.Exists(_path))
            {
                var _index = path.LastIndexOf('\\');
                var _name = path.Substring(_index + 1);
                return File(
                    new FileStream(_path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite),
                    "application/octet-stream",
                    _name);
            }
            else
            {
                return new EmptyResult();
            }
        }
    }
}